package level4.net.web.rfc1867impl
{
	import flash.utils.ByteArray;

	/**
	 * RFC1867格式化器
	 * 将请求按rfc1867(文件上传)格式,进行封装.
	 * 
	 * */
	public class RFC1867Formatter
	{
		//返回+换行
		public static const CR_LN:String 				= "\r\n";
		//分割符.
		private static const boundaryStr:String 		= "abc123";
		//表单内容类型
		public static const MultipartFormData:String 	= RFC1867EncType.MULTIPART + " boundary="+boundaryStr;
		//完整的分隔符
		public static const Boundary:String 			= "--"+boundaryStr;
		//部署格式的字符
		private static const preContentDisposition:String = 'Content-Disposition: form-data;';
		//此次form的完整自己数组
		private var bytes:ByteArray = new ByteArray();
		//静态实例
		public static const Instance:RFC1867Formatter = new RFC1867Formatter();
		
		public function RFC1867Formatter(){
		}
		/**
		 * 链式方法
		 * 作用,封装普通的表单数据.
		 * 将{key1:value,..}封装进bytes数组
		 * @param keyValues
		 * @return this
		 * */
		public function addValueBody(param:Object):RFC1867Formatter{
			for(var key:Object in param){
				writeUTFStringToBytes(Boundary).writeUTFStringToBytes(CR_LN);

				var arr:Array = [preContentDisposition];
				arr.push(' name="');
				arr.push(key);
				arr.push('"');
				
				writeUTFStringToBytes(arr.join(""));
				writeUTFStringToBytes(CR_LN);
				writeUTFStringToBytes(CR_LN);
				
				writeUTFStringToBytes(param[key]).writeUTFStringToBytes(CR_LN);
				writeUTFStringToBytes(Boundary).writeUTFStringToBytes(CR_LN);
			}
			return this;
		}
		
		/**
		 * 链式方法
		 * 作用:封装文件体.
		 * 将一个文件字节数组,按rfc1867 (http://www.ietf.org/rfc/rfc1867.txt)格式,进行封装
		 * @param fileName,
		 * @param fileBytes,
		 * @param contentType 此文件的内容类型,
		 * @param name:文件域的name,
		 * @return this.
		 * 以下为具体格式:
		 * //1,分隔符
		 * //2,换行
		 * //3,内容规划
		 * //4,换行
		 * //5,内容格式
		 * //6,换行
		 * //7,换行
		 * //8,写入文件字节
		 * //9,换行
		 * */
		public function addFileBody(fileName:String,fileBytes:ByteArray,contentType:String,name:String="name"):RFC1867Formatter{
			writeUTFStringToBytes(Boundary).writeUTFStringToBytes(CR_LN);
			writeUTFStringToBytes(getContentDisposition(name,fileName)).writeUTFStringToBytes(CR_LN);			
			writeUTFStringToBytes(contentType).	
			writeUTFStringToBytes(CR_LN).			
			writeUTFStringToBytes(CR_LN);
			//
			bytes.writeBytes(fileBytes,0,fileBytes.length);
			writeUTFStringToBytes(CR_LN);			
			return this;
		}
		
		/**
		 * 结束rfc1868格式封装.
		 * @return ByteArray
		 * */
		public function addTail():ByteArray{
			bytes.writeUTFBytes(Boundary);
			bytes.writeUTFBytes('--');
			return bytes;
		}
		///////////////////////////////////////////
		//工具方法
		///////////////////////////////////////////
		
		//以utf编码将str写入到bytes数组
		private function writeUTFStringToBytes(str:String):RFC1867Formatter{
			bytes.writeUTFBytes(str);
			return this;
		}
		/*
			组合 rfc1868需要的内容规划
			'Content-Disposition: form-data; name="name"; filename="'+fileName+'"';
		*/
		private function getContentDisposition(name:String,fileName:String):String{
			var arr:Array = [preContentDisposition];
			if(name){
				arr.push(' name="');//name前有空格
				arr.push(name);
				arr.push('"; ');//分号后又空格 
			}
			if(fileName){
				arr.push(' filename="');//有空格
				arr.push(fileName);
				arr.push('"');//无空格
			}
			return arr.join("");
		}
	}
}